home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_src.arc / ax25cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-08  |  14.3 KB  |  693 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "ax_mbx.h"
  6. #include "timer.h"
  7. #include "netuser.h"
  8. #include "ftp.h"
  9. #include "tcp.h"
  10. #include "telnet.h"
  11. #include "iface.h"
  12. #include "lapb.h"
  13. #include "finger.h"
  14. #include "cmdparse.h"
  15. #include "session.h"
  16. #include "nr4.h"
  17. /* heard stuff */
  18. #include "heard.h"
  19. /* heard stuff */
  20.  
  21. char *ax25states[] = {
  22.     "Disconnected",
  23.     "Conn pending",
  24.     "Disc pending",
  25.     "Connected",
  26.     "Recovery",
  27.     "Frame Reject",
  28. };
  29.  
  30. int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
  31.     doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh(),doheard();
  32. #ifdef SID2
  33. int dobbscall();
  34. extern struct ax25_addr bbscall;
  35. #endif
  36.  
  37. static struct cmds axcmds[] = {
  38.     "digipeat",    dodigipeat,    0, NULLCHAR,    NULLCHAR,
  39.     "maxframe",    domaxframe,    0, NULLCHAR,    NULLCHAR,
  40.     "mycall",    domycall,    0, NULLCHAR,    NULLCHAR,
  41. #ifdef SID2
  42.     "bbscall",    dobbscall,    0, NULLCHAR,    NULLCHAR,
  43. #endif
  44.     "paclen",    dopaclen,    0, NULLCHAR,    NULLCHAR,
  45.     "pthresh",    dopthresh,    0, NULLCHAR,    NULLCHAR,
  46.     "reset",    doaxreset,    2, "ax25 reset <axcb>", NULLCHAR,
  47.     "retry",    don2,        0, NULLCHAR,    NULLCHAR,
  48.     "status",    doaxstat,    0, NULLCHAR,    NULLCHAR,
  49.     "t1",        dot1,        0, NULLCHAR,    NULLCHAR,
  50.     "t2",        dot2,        0, NULLCHAR,    NULLCHAR,
  51.     "t3",        dot3,        0, NULLCHAR,    NULLCHAR,
  52.     "window",    doaxwindow,    0, NULLCHAR,    NULLCHAR,
  53. /* heard stuff */
  54.     "heard",    doheard,    0, NULLCHAR,    NULLCHAR,
  55. /* heard stuff */
  56. #ifdef SID2
  57.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat heard maxframe mycall bbscall paclen pthresh reset\n\t\tretry status t1 t2 t3 window",    NULLCHAR,
  58. #else
  59.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat heard maxframe mycall paclen pthresh reset retry\n\t\tstatus t1 t2 t3 window",    NULLCHAR,
  60. #endif
  61. };
  62.  
  63. /* Multiplexer for top-level ax25 command */
  64. doax25(argc,argv)
  65. int argc;
  66. char *argv[];
  67. {
  68.     return subcmd(axcmds,argc,argv);
  69. }
  70.  
  71. static
  72. doaxreset(argc,argv)
  73. int argc;
  74. char *argv[];
  75. {
  76.     struct ax25_cb *axp;
  77.     extern char notval[];
  78.  
  79.     axp = (struct ax25_cb *)htol(argv[1]);
  80.     if(!ax25val(axp)){
  81.         printf(notval);
  82.         return 1;
  83.     }
  84.     reset_ax25(axp);
  85.     return 0;
  86. }
  87.  
  88. /* Display AX.25 link level control blocks */
  89. static
  90. doaxstat(argc,argv)
  91. int argc;
  92. char *argv[];
  93. {
  94.     register int i;
  95.     register struct ax25_cb *axp;
  96.     char tmp[10];
  97.     extern char notval[];
  98.  
  99.     if(argc < 2){
  100.         printf("    &AXB IF   Snd-Q   Rcv-Q   Remote    State\n");
  101.         for(i=0;i<NHASH;i++){
  102.             for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
  103.                 pax25(tmp,&axp->addr.dest);
  104.                 printf("%8lx %-5s%-8d%-8d%-10s%s\n",
  105.                     (long)axp,axp->interface->name,
  106.                     len_q(axp->txq),len_mbuf(axp->rxq),
  107.                     tmp,ax25states[axp->state]);
  108.             }
  109.         }
  110.         return 0;
  111.     }
  112.     axp = (struct ax25_cb *)htol(argv[1]);
  113.     if(!ax25val(axp)){
  114.         printf(notval);
  115.         return 1;
  116.     }
  117.     dumpstat(axp);
  118.     return 0;
  119. }
  120. /* Dump one control block */
  121. static
  122. dumpstat(axp)
  123. register struct ax25_cb *axp;
  124. {
  125.     char tmp[10];
  126.     int i;
  127.  
  128.     if(axp == NULLAX25 || axp->interface == NULLIF)
  129.         return;
  130.     printf("&AXB IF   Remote   RB V(S) V(R) Unack P Retry State\n");
  131.     pax25(tmp,&axp->addr.dest);
  132.     printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
  133.     putchar(axp->rejsent ? 'R' : ' ');
  134.     putchar(axp->remotebusy ? 'B' : ' ');
  135.     printf(" %4d %4d",axp->vs,axp->vr);
  136.     printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  137.     printf(" %02u/%02u",axp->retries,axp->n2);
  138.     printf(" %s\n",ax25states[axp->state]);
  139.  
  140.     printf("T1: ");
  141.     if(run_timer(&axp->t1))
  142.         printf("%lu",(axp->t1.start - axp->t1.count) * MSPTICK);
  143.     else
  144.         printf("stop");
  145.     printf("/%lu ms; ",axp->t1.start * MSPTICK);
  146.  
  147.     printf("T2: ");
  148.     if(run_timer(&axp->t2))
  149.         printf("%lu",(axp->t2.start - axp->t2.count) * MSPTICK);
  150.     else
  151.         printf("stop");
  152.     printf("/%lu ms; ",axp->t2.start * MSPTICK);
  153.  
  154.     printf("T3: ");
  155.     if(run_timer(&axp->t3))
  156.         printf("%lu",(axp->t3.start - axp->t3.count) * MSPTICK);
  157.     else
  158.         printf("stop");
  159.     printf("/%lu ms\n",axp->t3.start * MSPTICK);
  160.  
  161.     if(axp->addr.ndigis == 0)
  162.         return;
  163.     printf("Digipeaters:");
  164.     for(i=0;i<axp->addr.ndigis;i++){
  165.         pax25(tmp,&axp->addr.digis[i]);
  166.         printf(" %s",tmp);
  167.     }
  168.     printf("\n");
  169. }
  170.  
  171. /* Display or change our AX.25 address */
  172. static
  173. domycall(argc,argv)
  174. int argc;
  175. char *argv[];
  176. {
  177.     char buf[15];
  178.  
  179.     if(argc < 2){
  180.         pax25(buf,&mycall);
  181.         printf("%s\n",buf);
  182.         return 0;
  183.     }
  184.     if(setcall(&mycall,argv[1]) == -1)
  185.         return -1;
  186.     mycall.ssid |= E;
  187.     return 0;
  188. }
  189.  
  190. #ifdef SID2
  191. /* Display or change our AX.25 BBS address */
  192. static
  193. dobbscall(argc,argv)
  194. int argc;
  195. char *argv[];
  196. {
  197.     char buf[15];
  198.  
  199.     if(argc < 2){
  200.         pax25(buf,&bbscall);
  201.         printf("%s\n",buf);
  202.         return 0;
  203.     }
  204.     if(setcall(&bbscall,argv[1]) == -1)
  205.         return -1;
  206.     bbscall.ssid |= E;
  207.     return 0;
  208. }
  209. #endif
  210.  
  211. /* Control AX.25 digipeating */
  212. static
  213. dodigipeat(argc,argv)
  214. int argc;
  215. char *argv[];
  216. {
  217.     extern int digipeat;
  218.  
  219.     if(argc == 1) {
  220.         printf("digipeat %s\n",digipeat ? "on" : "off");
  221.     } else {
  222.         if(strcmp(argv[1],"on") == 0)
  223.             digipeat = 1;
  224.         else
  225.             digipeat = 0;
  226.     }
  227. }
  228.  
  229. /* Set retransmission timer */
  230. static
  231. dot1(argc,argv)
  232. int argc;
  233. char *argv[];
  234. {
  235.     extern int16 t1init;
  236.  
  237.     if(argc == 1) {
  238.         printf("T1 %lu ms\n",(long)t1init * MSPTICK);
  239.     } else {
  240.         t1init = atol(argv[1]) / MSPTICK;
  241.     }
  242. }
  243.  
  244. /* Set acknowledgement delay timer */
  245. static
  246. dot2(argc,argv)
  247. int argc;
  248. char *argv[];
  249. {
  250.     extern int16 t2init;
  251.  
  252.     if(argc == 1) {
  253.         printf("T2 %lu ms\n",(long)t2init * MSPTICK);
  254.     } else {
  255.         t2init = atol(argv[1]) / MSPTICK;
  256.     }
  257. }
  258.  
  259. /* Set idle timer */
  260. static
  261. dot3(argc,argv)
  262. int argc;
  263. char *argv[];
  264. {
  265.     extern int16 t3init;
  266.  
  267.     if(argc == 1) {
  268.         printf("T3 %lu ms\n",(long)t3init * MSPTICK);
  269.     } else {
  270.         t3init = atol(argv[1]) / MSPTICK;
  271.     }
  272. }
  273.  
  274. /* Set retry limit count */
  275. static
  276. don2(argc,argv)
  277. int argc;
  278. char *argv[];
  279. {
  280.     extern int16 n2;
  281.  
  282.     if(argc == 1) {
  283.         printf("Retry %u\n",n2);
  284.     } else {
  285.         n2 = atoi(argv[1]);
  286.     }
  287. }
  288.  
  289. /* Set maximum number of frames that will be allowed in flight */
  290. static
  291. domaxframe(argc,argv)
  292. int argc;
  293. char *argv[];
  294. {
  295.     extern int16 maxframe;
  296.  
  297.     if(argc == 1) {
  298.         printf("Maxframe %u\n",maxframe);
  299.     } else {
  300.         maxframe = atoi(argv[1]);
  301.     }
  302. }
  303.  
  304. /* Set maximum length of I-frame data field */
  305. static
  306. dopaclen(argc,argv)
  307. int argc;
  308. char *argv[];
  309. {
  310.     extern int16 paclen;
  311.  
  312.     if(argc == 1) {
  313.         printf("Paclen %u\n",paclen);
  314.     } else {
  315.         paclen = atoi(argv[1]);
  316.     }
  317. }
  318. /* Set size of I-frame above which polls will be sent after a timeout */
  319. static
  320. dopthresh(argc,argv)
  321. int argc;
  322. char *argv[];
  323. {
  324.     extern int16 pthresh;
  325.  
  326.     if(argc == 1) {
  327.         printf("Pthresh %u\n",pthresh);
  328.     } else {
  329.         pthresh = atoi(argv[1]);
  330.     }
  331. }
  332.  
  333. /* Set high water mark on receive queue that triggers RNR */
  334. static
  335. doaxwindow(argc,argv)
  336. int argc;
  337. char *argv[];
  338. {
  339.     extern int16 axwindow;
  340.  
  341.     if(argc == 1) {
  342.         printf("Axwindow %u\n",axwindow);
  343.     } else {
  344.         axwindow = atoi(argv[1]);
  345.     }
  346. }
  347. /* End of ax25 subcommands */
  348.  
  349. /* Initiate interactive AX.25 connect to remote station */
  350. doconnect(argc,argv)
  351. int argc;
  352. char *argv[];
  353.  {
  354.     void ax_rx(),ax_tx(),ax_state();
  355.     int ax_parse();
  356.     struct ax25_addr dest;
  357.     struct ax25 addr;
  358.     struct ax25_cb *open_ax25();
  359.     struct interface *ifp;
  360.     struct session *s;
  361.     extern int16 axwindow;
  362.     int i;
  363.  
  364.     if (strcmp(argv[1],"netrom") == 0) {
  365.         printf("Connect on netrom interface not supported\n") ;
  366.         return 1 ;
  367.     }
  368.     
  369.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  370.         if(strcmp(argv[1],ifp->name) == 0)
  371.             break;
  372.  
  373.     if(ifp == NULLIF){
  374.         printf("Interface %s unknown\n",argv[1]);
  375.         return 1;
  376.     }
  377.     setcall(&dest,argv[2]);
  378.     /* See if a session already exists */
  379.     for(s = sessions; s < &sessions[nsessions]; s++){
  380.         if(s->type == AX25TNC
  381.          && addreq(&s->cb.ax25_cb->addr.dest,&dest)){
  382. #if    (defined(MAC) || defined(AMIGA))
  383.             printf("Session %lu to %s already exists\n",
  384. #else
  385.             printf("Session %u to %s already exists\n",
  386. #endif
  387.                 s - sessions,argv[2]);
  388.             return 1;
  389.         }
  390.     }
  391.     /* Allocate a session descriptor */
  392.     if((s = newsession()) == NULLSESSION){
  393.         printf("Too many sessions\n");
  394.         return 1;
  395.     }
  396.     if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
  397.         strcpy(s->name,argv[2]);
  398.     s->type = AX25TNC;
  399.     s->parse = ax_parse;
  400.     current = s;
  401.     ASSIGN(addr.source,mycall);
  402.     setcall(&addr.dest,argv[2]);
  403.     for(i=3; i < argc; i++)
  404.         setcall(&addr.digis[i-3],argv[i]);
  405.  
  406.     addr.ndigis = i - 3;
  407.     s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
  408.     go();
  409.     return 0;
  410. }
  411.  
  412.  
  413. /* Display changes in AX.25 state */
  414. void
  415. ax_state(axp,old,new)
  416. struct ax25_cb *axp;
  417. int old,new;
  418. {
  419.     struct session *s;
  420.  
  421.     s = (struct session *)axp->user;
  422.  
  423.     if(current != NULLSESSION && current->type == AX25TNC && current == s){
  424.         /* Don't print transitions between CONNECTED and RECOVERY */
  425.         if(new != RECOVERY && !(old == RECOVERY && new == CONNECTED))
  426.             printf("%s\n",ax25states[new]);
  427.         if(new == DISCONNECTED)
  428.             cmdmode();
  429.         fflush(stdout);
  430.     }
  431.     if(new == DISCONNECTED){
  432.         axp->user = NULLCHAR;
  433.         freesession(s);
  434.     }
  435. }
  436. /* Handle typed characters on AX.25 connection */
  437. int
  438. ax_parse(buf,cnt)
  439. char *buf;
  440. int16 cnt;
  441. {
  442.     struct mbuf *bp;
  443.     register char *cp;
  444.     char c;
  445.  
  446.     if(current == NULLSESSION || current->type != AX25TNC)
  447.         return;    /* "can't happen" */
  448.  
  449.     /* If recording is on, record outgoing stuff too */
  450.     if(current->record != NULLFILE)
  451.         fwrite(buf,1,cnt,current->record);
  452.  
  453.     /* Allocate buffer and start it with the PID */
  454.     bp = alloc_mbuf(cnt+1);
  455.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
  456.     bp->cnt++;
  457.  
  458.     /* Copy keyboard buffer to output, stripping line feeds */
  459.     cp = bp->data + 1;
  460.     while(cnt-- != 0){
  461.         c = *buf++;
  462.         if(c != '\n'){
  463.             *cp++ = c;
  464.             bp->cnt++;
  465.         }
  466.     }
  467.     send_ax25(current->cb.ax25_cb,bp);
  468. }
  469. /* Handle new incoming terminal sessions
  470.  * This is the default receive upcall function, used when
  471.  * someone else connects to us
  472.  */
  473. void
  474. ax_incom(axp,cnt)
  475. register struct ax25_cb *axp;
  476. int16 cnt;
  477. {
  478.     void ax_session() ;
  479.     
  480.     if (ax25mbox)
  481.         mbx_incom(axp,cnt) ;
  482.     else
  483.         ax_session(axp,cnt) ;
  484.     return ;
  485.  
  486. }
  487.  
  488. /* This function sets up an ax25 chat session */
  489. void
  490. ax_session(axp,cnt)
  491. register struct ax25_cb *axp ;
  492. int16 cnt ;
  493. {
  494.     struct session *s;
  495.     char remote[10];
  496.     void ax_rx(),ax_state(),ax_tx();
  497.  
  498.     pax25(remote,&axp->addr.dest);
  499.     if((s = newsession()) == NULLSESSION){
  500.         /* Out of sessions */
  501.         disc_ax25(axp);
  502.         return;
  503.     }
  504.     s->type = AX25TNC;
  505.     s->name = malloc((int16)strlen(remote)+1);
  506.     s->cb.ax25_cb = axp;
  507.     s->parse = ax_parse;
  508.     strcpy(s->name,remote);
  509.     axp->r_upcall = ax_rx;
  510.     axp->s_upcall = ax_state;
  511.     axp->t_upcall = ax_tx;
  512.     axp->user = (char *)s;
  513. #if    (defined(MAC) || defined(AMIGA))
  514.     printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
  515. #else
  516.     printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
  517. #endif
  518.     fflush(stdout);
  519. }
  520.  
  521. /* Handle incoming terminal traffic */
  522. void
  523. ax_rx(axp,cnt)
  524. struct ax25_cb *axp;
  525. int16 cnt;
  526. {
  527.     register struct mbuf *bp;
  528.     struct mbuf *recv_ax25();
  529.     char c;
  530.  
  531.     /* Hold output if we're not the current session */
  532.     if(mode != CONV_MODE || current == NULLSESSION
  533.      || current->type != AX25TNC || current->cb.ax25_cb != axp)
  534.         return;
  535.  
  536.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)
  537.         return;
  538.  
  539.     /* Display received characters, translating CR's to CR/LF */
  540.     while(bp != NULLBUF){
  541.         while(bp->cnt-- != 0){
  542.             c = *bp->data++;
  543.             if(c == '\r')
  544.                 c = '\n';
  545.             putchar(c);
  546.             if(current->record){
  547. #ifndef UNIX
  548.                 if(c == '\n')
  549.                     fputc('\r',current->record);
  550. #endif
  551.                 fputc(c,current->record);
  552.             }
  553.         }
  554.         bp = free_mbuf(bp);
  555.     }
  556.     if(current->record)
  557.         fflush(current->record);
  558.     fflush(stdout);
  559. }
  560. /* Handle transmit upcalls. Used only for file uploading */
  561. void
  562. ax_tx(axp,cnt)
  563. struct ax25_cb *axp;
  564. int16 cnt;
  565. {
  566.     register char *cp;
  567.     struct session *s;
  568.     register struct mbuf *bp;
  569.     int16 size;
  570.     int c;
  571.  
  572.     if((s = (struct session *)axp->user) == NULLSESSION
  573.      || s->upload == NULLFILE)
  574.         return;
  575.     while(cnt != 0){
  576.         size = min(cnt,axp->paclen+1);
  577.         if((bp = alloc_mbuf(size)) == NULLBUF)
  578.             break;
  579.         cp = bp->data;
  580.         /* Start with the PID */
  581.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  582.         bp->cnt++;
  583.  
  584.         /* Now send data characters, translating between local
  585.          * keyboard end-of-line sequences and the (unwritten)
  586.          * AX.25 convention, which is carriage-return only
  587.          */
  588.         while(bp->cnt < size){
  589.             if((c = getc(s->upload)) == EOF)
  590.                 break;
  591. #ifdef    MSDOS
  592.             /* MS-DOS gives cr-lf */
  593.             if(c == '\n')
  594.                 continue;
  595. #endif
  596. #if    (defined(UNIX) || defined(MAC) || defined(AMIGA))
  597.             /* These give lf only */
  598.             if(c == '\n')
  599.                 c = '\r';
  600. #endif
  601.             *cp++ = c;
  602.             bp->cnt++;
  603.         }    
  604.         if(bp->cnt > 1) {
  605.             send_ax25(axp,bp);
  606.         } else {
  607.             /* Empty frame, don't bother sending */
  608.             free_p(bp);
  609.             break;
  610.         }
  611.         cnt -= bp->cnt;
  612.     }
  613.     if(cnt != 0){
  614.         /* Error or end-of-file */
  615.         fclose(s->upload);
  616.         s->upload = NULLFILE;
  617.         free(s->ufile);
  618.         s->ufile = NULLCHAR;
  619.     }
  620. }
  621.  
  622. /* heard stuff */
  623. struct ax25_heard heard = {0,0};
  624. /* Display AX.25 heard list */
  625. static
  626. doheard(argc,argv)
  627. int argc;
  628. char *argv[];
  629. {
  630.     struct heard_stuff *hp;
  631.     struct ax25_addr *dp;
  632.     extern struct ax25_heard heard;
  633.     char tmp[16];
  634.     int16 curr;
  635.     long t;
  636.  
  637.     if(argc < 2) {
  638.         if (!heard.enabled) {
  639.             printf("not enabled\n");
  640.             return(0);
  641.         }
  642.         time(&t);
  643.         printf("\nHeard list: %s\n",ctime(&t));
  644.         curr = heard.first;
  645.         while (curr != -1) {
  646.             hp = &heard.list[curr];
  647.             pax25(tmp,&hp->info.source);
  648.             printf("%-10s",tmp);
  649.             if(hp->info.ndigis > 0){
  650.                 printf(" (via");
  651.                 /* Print digi string until packet got to us */
  652.                 for(dp = &hp->info.digis[0]; dp < &hp->info.digis[hp->info.ndigis]; dp++){
  653.                     if (dp->ssid & REPEATED) {
  654.                         pax25(tmp,dp);
  655.                         printf(" %s",tmp);
  656.                     } else {
  657.                         break;
  658.                     }
  659.                 }
  660.                 printf(")");
  661.             }
  662.             if (hp->flags) {
  663.                 printf("%-5s%-8s%-4s",
  664.                                 (hp->flags & HEARD_ARP) ? " ARP" : "",
  665.                                 (hp->flags & HEARD_NETROM) ? " NETROM" : "",
  666.                                 (hp->flags & HEARD_IP) ? " IP" : "");
  667.             }
  668.             printf("  %s", ctime(&hp->htime));
  669.             curr = hp->next;
  670.         }
  671.         return 0;
  672.     }
  673.     if (strcmp(argv[1],"clear") == 0) {
  674.         heard.cnt = 0;
  675.         heard.first = -1;
  676.         return 0;
  677.     } else if (strcmp(argv[1],"on") == 0) {
  678.         if (!heard.enabled) {
  679.             heard.enabled = 1;
  680.             heard.cnt = 0;
  681.             heard.first = -1;
  682.         }
  683.         return 0;
  684.     } else if (strcmp(argv[1],"off") == 0) {
  685.         heard.enabled = 0;
  686.         return 0;
  687.     } else {
  688.         printf("Usage: ax25 heard [ on | off | clear ]\n");
  689.     }
  690.     return 0;
  691. }
  692. /* heard stuff */
  693.